package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)



type Middleware func(http.HandlerFunc) http.HandlerFunc

func Logging() Middleware{
	// create a middleware
	return func(hf http.HandlerFunc) http.HandlerFunc {
		// create a http.HandlerFunc
		return func(w http.ResponseWriter, r *http.Request) {
			// middleware function works here
			start := time.Now()
			defer func ()  {
				log.Println(r.URL.Path,time.Since(start))
			}()
			// call the next middleware/handler in chain
			hf(w,r)
		}
	}
}

func Method(m string) Middleware{
	return func(hf http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			if r.Method != m{
				http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
                return
			}
			hf(w,r)
		}
	}
}

// Chain applies middlewares to a http.HandlerFunc
func Chain(f http.HandlerFunc,ms... Middleware) http.HandlerFunc{
	for _,middleware := range ms{
		f = middleware(f)
	}
	return f
}

// http.HandleFunc
func hello(w http.ResponseWriter,r *http.Request){
	fmt.Fprintln(w,"Hello there")
}

func main(){
	http.HandleFunc("/",Chain(hello,Method("GET"),Logging()))
	http.ListenAndServe(":8080",nil)
}